/*
 * sintatico.c
 *
 *  Created on: Oct 28, 2011
 *      Author: Fernando
 */

#include <stdio.h>
#include <string.h>
#include "ape.h"
#include "lexico.h"
#include "sintatico.h"
#include "debug.h"

static int erroSintatico = 0;

int executarAnalisadorSintatico() {
	Token* pToken;
	while ((pToken = proximoToken()) != NULL) {
		if (pToken->classe == INVALID_TOKEN)
			continue;
#if DEBUG_SINTATICO == 1
		if (pToken->classe == INTEGER)
			printf(">> Processando token: [%s] %d\n", classeTokenToString(pToken->classe), pToken->representacaoInt);
		else if (pToken->classe == FLOAT)
			printf(">> Processando token: [%s] %f\n", classeTokenToString(pToken->classe), pToken->representacaoFloat);
		else
			printf(">> Processando token: [%s] %s\n", classeTokenToString(pToken->classe), pToken->representacaoString);
#endif

		ApeTokenId apeTokenId = identificarToken(*pToken);
		if (apeTokenId == -1) {
			printf("Erro: Falha ao identificar o token recebido");
			erroSintatico = 1;
			break;
		}

		if (processarTransicaoAPE(*pToken, apeTokenId) == 0) {
			printf("Erro: Nenhuma transicao valida no APE para o token recebido\n");
			erroSintatico = 1;
			break;
		}
	}

	if (cadeiaAceita() && erroLexico == 0 && erroSintatico == 0) {
		printf("Arquivo de entrada aceito e processado com sucesso!\n");
		return 1;
	}

	// Erros :(
	if (erroLexico != 0) {
		printf("Um ou mais erros lexicos foram detectados no arquivo de entrada\n");
	}
	if (erroSintatico != 0) {
		printf("Um ou mais erros sintaticos foram detectados no arquivo de entrada\n");
	}
	if (!cadeiaAceita()) {
		printf("Arquivo de entrada NAO aceito\n");
	}
	return 0;
}

ApeTokenId identificarToken(Token token) {
	if (token.classe == IDENTIFIER)
		return APE_TOKEN_NOME;
	else if (token.classe == STRING_LITERAL || token.classe == TEXT || token.classe == CHARACTER)
		return APE_TOKEN_LITERAL_STRING;
	else if (token.classe == INTEGER || token.classe == FLOAT)
		return APE_TOKEN_NUMERO;
	else if (token.classe == RESERVED_KEYWORD) {
		if (strcmp(token.representacaoString, "program") == 0)
			return APE_TOKEN_RSV_PROGRAM;
		else if (strcmp(token.representacaoString, "begin") == 0)
			return APE_TOKEN_RSV_BEGIN;
		else if (strcmp(token.representacaoString, "end") == 0)
			return APE_TOKEN_RSV_END;
		else if (strcmp(token.representacaoString, "declare") == 0)
			return APE_TOKEN_RSV_DECLARE;
		else if (strcmp(token.representacaoString, "int") == 0)
			return APE_TOKEN_RSV_INT;
		else if (strcmp(token.representacaoString, "float") == 0)
			return APE_TOKEN_RSV_FLOAT;
		else if (strcmp(token.representacaoString, "char") == 0)
			return APE_TOKEN_RSV_CHAR;
		else if (strcmp(token.representacaoString, "string") == 0)
			return APE_TOKEN_RSV_STRING;
		else if (strcmp(token.representacaoString, "boolean") == 0)
			return APE_TOKEN_RSV_BOOLEAN;
		else if (strcmp(token.representacaoString, "not") == 0)
			return APE_TOKEN_RSV_NOT;
		else if (strcmp(token.representacaoString, "and") == 0)
			return APE_TOKEN_RSV_AND;
		else if (strcmp(token.representacaoString, "or") == 0)
			return APE_TOKEN_RSV_OR;
		else if (strcmp(token.representacaoString, "true") == 0)
			return APE_TOKEN_RSV_TRUE;
		else if (strcmp(token.representacaoString, "false") == 0)
			return APE_TOKEN_RSV_FALSE;
		else if (strcmp(token.representacaoString, "if") == 0)
			return APE_TOKEN_RSV_IF;
		else if (strcmp(token.representacaoString, "then") == 0)
			return APE_TOKEN_RSV_THEN;
		else if (strcmp(token.representacaoString, "elif") == 0)
			return APE_TOKEN_RSV_ELIF;
		else if (strcmp(token.representacaoString, "else") == 0)
			return APE_TOKEN_RSV_ELSE;
		else if (strcmp(token.representacaoString, "endif") == 0)
			return APE_TOKEN_RSV_ENDIF;
		else if (strcmp(token.representacaoString, "while") == 0)
			return APE_TOKEN_RSV_WHILE;
		else if (strcmp(token.representacaoString, "endwhile") == 0)
			return APE_TOKEN_RSV_ENDWHILE;
		else if (strcmp(token.representacaoString, "for") == 0)
			return APE_TOKEN_RSV_FOR;
		else if (strcmp(token.representacaoString, "endfor") == 0)
			return APE_TOKEN_RSV_ENDFOR;
		else if (strcmp(token.representacaoString, "continue") == 0)
			return APE_TOKEN_RSV_CONTINUE;
		else if (strcmp(token.representacaoString, "break") == 0)
			return APE_TOKEN_RSV_BREAK;
		else if (strcmp(token.representacaoString, "function") == 0)
			return APE_TOKEN_RSV_FUNCTION;
		else if (strcmp(token.representacaoString, "void") == 0)
			return APE_TOKEN_RSV_VOID;
		else if (strcmp(token.representacaoString, "return") == 0)
			return APE_TOKEN_RSV_RETURN;
		else if (strcmp(token.representacaoString, "endfunction") == 0)
			return APE_TOKEN_RSV_ENDFUNCTION;
		else if (strcmp(token.representacaoString, "call") == 0)
			return APE_TOKEN_RSV_CALL;
		else if (strcmp(token.representacaoString, "switch") == 0)
			return APE_TOKEN_RSV_SWITCH;
		else if (strcmp(token.representacaoString, "case") == 0)
			return APE_TOKEN_RSV_CASE;
		else if (strcmp(token.representacaoString, "default") == 0)
			return APE_TOKEN_RSV_DEFAULT;
		else if (strcmp(token.representacaoString, "endswitch") == 0)
			return APE_TOKEN_RSV_ENDSWITCH;
		else if (strcmp(token.representacaoString, "input") == 0)
			return APE_TOKEN_RSV_INPUT;
		else if (strcmp(token.representacaoString, "output") == 0)
			return APE_TOKEN_RSV_OUTPUT;
		else if (strcmp(token.representacaoString, "struct") == 0)
			return APE_TOKEN_RSV_STRUCT;
		else if (strcmp(token.representacaoString, "endstruct") == 0)
			return APE_TOKEN_RSV_ENDSTRUCT;
	}
	else if (token.classe == SPECIAL_CHARACTER) {
		if (strcmp(token.representacaoString, "+") == 0)
			return APE_TOKEN_SYM_SOMA;
		else if (strcmp(token.representacaoString, "-") == 0)
			return APE_TOKEN_SYM_SUBTRACAO;
		else if (strcmp(token.representacaoString, "*") == 0)
			return APE_TOKEN_SYM_MULTIPLICACAO;
		else if (strcmp(token.representacaoString, "/") == 0)
			return APE_TOKEN_SYM_DIVISAO;
		else if (strcmp(token.representacaoString, "(") == 0)
			return APE_TOKEN_SYM_ABRE_PARENTESIS;
		else if (strcmp(token.representacaoString, ")") == 0)
			return APE_TOKEN_SYM_FECHA_PARENTESIS;
		else if (strcmp(token.representacaoString, "[") == 0)
			return APE_TOKEN_SYM_ABRE_COLCHETE;
		else if (strcmp(token.representacaoString, "]") == 0)
			return APE_TOKEN_SYM_FECHA_COLCHETE;
		else if (strcmp(token.representacaoString, "=") == 0)
			return APE_TOKEN_SYM_ATRIBUICAO;
		else if (strcmp(token.representacaoString, "<") == 0)
			return APE_TOKEN_SYM_MENOR;
		else if (strcmp(token.representacaoString, ">") == 0)
			return APE_TOKEN_SYM_MAIOR;
		else if (strcmp(token.representacaoString, ",") == 0)
			return APE_TOKEN_SYM_VIRGULA;
		else if (strcmp(token.representacaoString, ":") == 0)
			return APE_TOKEN_SYM_DOIS_PONTOS;
		else if (strcmp(token.representacaoString, ";") == 0)
			return APE_TOKEN_SYM_PONTO_VIRGULA;
		else if (strcmp(token.representacaoString, "!=") == 0)
			return APE_TOKEN_SYM_DIFERENTE;
		else if (strcmp(token.representacaoString, "==") == 0)
			return APE_TOKEN_SYM_IGUAL;
		else if (strcmp(token.representacaoString, "<=") == 0)
			return APE_TOKEN_SYM_MENOR_IGUAL;
		else if (strcmp(token.representacaoString, ">=") == 0)
			return APE_TOKEN_SYM_MAIOR_IGUAL;
	}
	return -1;
}
